package com.learning.spring.aop.aspectj.pointcut.expression.function;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/**
 * ClassName: MethodPointcutFunction
 * Description: 方法切点函数：@annotation、execution
 * Date: 2020/10/15 10:25 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
@Aspect
public class MethodPointcutFunction {

    /**
     * 1. 注解 @annotation 表示标注了某个注解的所有方法。
     * 2. 切点为标注了 @LogEntity 注解的方法
     */
    @Before("@annotation(com.learning.spring.aop.aspectj.pointcut.expression.annotation.LogEntity)")
    public void annotation() {
        System.out.println("Hello @annotation Function");
    }

    /**
     * 1. execution 是最常用的切点函数，语法为
     * execution (<修饰符类型>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)
     * <p>
     * 2. 方法签名定义切点
     * 2.1 execution(public * *(..)) ：匹配所有目标类的 public 方法
     * 第一个 `*` ：返回类型
     * 第二个 `*` ：方法名
     * 方法中 `..` ：任意参数
     * <p>
     * 2.2 execution(* *To(..)) ：匹配目标类所有以To为后缀的方法
     */
    @Before("execution(public * *(..))")
    public void executionMethod() {
        System.out.println("Hello execution(public * *(..)) Function");
    }

    /**
     * 1. 类定义切点
     * 1.1 execution(* com.learning.spring.aop.aspectj.pointcut.expression.service.AopService.*(..)) 匹配 AopService 接口的所有方法
     * 1.2 execution(* com.learning.spring.aop.aspectj.pointcut.expression.service.AopService+.*(..)) 匹配 AopService 接口及其实现类的所有方法。包括实现类的私有的方法。
     */
    @Before("execution(* com.learning.spring.aop.aspectj.pointcut.expression.service.AopService.*(..))")
    public void executionClazz() {
        System.out.println("Hello execution(* com.learning.spring.aop.aspectj.pointcut.expression.service.AopService.*(..)) Function");
    }

    /**
     * 1. 类包定义切点
     * .* 包下所有的类
     * ..* 包和子孙包
     * <p>
     * 2. 例子
     * execution(* com.learning.spring.aop.aspectj.*(..)) 匹配 com.learning.spring.aop.aspectj.pointcut.expression 包下所有类所有方法
     * execution(* com.learning.spring.aop.aspectj..*(..)) 匹配 com.learning.spring.aop.aspectj.pointcut.expression 包下,子孙包下所有类所有方法
     * execution(* com.learning.spring.aop..*.*Service.find*(..)) 匹配 com.learning.spring.aop.aspectj.pointcut.expression 任意包下 Service 后缀的类，前缀为 find 的方法
     */
    @Before("execution(* com.learning.spring.aop.aspectj.pointcut.expression..*(..))")
    public void executionPackage() {
        System.out.println("Hello execution(* com.learning.spring.aop.aspectj.pointcut.expression..*(..)) Function");
    }


    /**
     * 1. 方法入参定义切点
     * 2. 例子：
     * execution(* add(String)) 匹配 add(String) 方法，且方法参数类型是 String
     */
    @Before("execution(* add(String))")
    public void executionMethodArgs() {
        System.out.println("Hello execution(* add(String)) Function");
    }
}
